/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.biz.service.impl;

import me.zhengjie.modules.biz.domain.*;
import me.zhengjie.modules.biz.repository.LabRepository;
import me.zhengjie.modules.biz.repository.LockRepository;
import me.zhengjie.modules.biz.repository.OpendoorrecordRepository;
import me.zhengjie.modules.biz.service.dto.IncubatorLogDto;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.service.vo.R;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.biz.repository.RefrigeratorRepository;
import me.zhengjie.modules.biz.service.RefrigeratorService;
import me.zhengjie.modules.biz.service.dto.RefrigeratorDto;
import me.zhengjie.modules.biz.service.dto.RefrigeratorQueryCriteria;
import me.zhengjie.modules.biz.service.mapstruct.RefrigeratorMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.lang.System;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
 * @author Admin
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2023-02-17
 **/
@Service
@RequiredArgsConstructor
public class RefrigeratorServiceImpl implements RefrigeratorService {

    private final RefrigeratorRepository refrigeratorRepository;
    private final RefrigeratorMapper refrigeratorMapper;
    private final LabRepository labRepository;
    private final UserRepository userRepository;
    private final LockRepository lockRepository;
    private final OpendoorrecordRepository opendoorrecordRepository;


    @Override
    public Map<String, Object> queryAll(RefrigeratorQueryCriteria criteria, Pageable pageable) {
        Page<Refrigerator> page = refrigeratorRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<RefrigeratorDto> dto = page.map(refrigeratorMapper::toDto);
        List<RefrigeratorDto> resultDto = dto.getContent();
        for (RefrigeratorDto refrigeratorDto : resultDto) {
            Lab lab = labRepository.findById(refrigeratorDto.getLabId()).orElseGet(Lab::new);
            User user = userRepository.findById(Long.valueOf(refrigeratorDto.getAdministrator())).orElseGet(User::new);
            refrigeratorDto.setLabName(lab.getName());
            refrigeratorDto.setAdministratorName(user.getUsername());
        }
        return PageUtil.toPage(dto);
    }

    @Override
    public List<RefrigeratorDto> queryAll(RefrigeratorQueryCriteria criteria) {
        List<Refrigerator> refrigeratorList = refrigeratorRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder));
        List<RefrigeratorDto> refrigeratorDtoList = refrigeratorMapper.toDto(refrigeratorList);
        for (RefrigeratorDto refrigeratorDto : refrigeratorDtoList) {
            Lab lab = labRepository.findById(refrigeratorDto.getLabId()).orElseGet(Lab::new);
            User user = userRepository.findById(Long.valueOf(refrigeratorDto.getAdministrator())).orElseGet(User::new);
            refrigeratorDto.setLabName(lab.getName());
            refrigeratorDto.setAdministratorName(user.getUsername());
        }
        return refrigeratorDtoList;
    }

    @Override
    @Transactional
    public RefrigeratorDto findById(Integer id) {
        Refrigerator refrigerator = refrigeratorRepository.findById(id).orElseGet(Refrigerator::new);
        ValidationUtil.isNull(refrigerator.getId(), "Refrigerator", "id", id);
        return refrigeratorMapper.toDto(refrigerator);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RefrigeratorDto create(Refrigerator resources) {
        resources.setIsOpen(0);
        RefrigeratorDto refrigeratorDto = refrigeratorMapper.toDto(refrigeratorRepository.save(resources));
        Lock lock = new Lock();
        lock.setIsOpen(0);
        lock.setCid(resources.getId());
        lock.setType(3);
        lock.setMac(resources.getMac());
        lockRepository.save(lock);
        return refrigeratorDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Refrigerator resources) {
        Refrigerator refrigerator = refrigeratorRepository.findById(resources.getId()).orElseGet(Refrigerator::new);
        ValidationUtil.isNull(refrigerator.getId(), "Refrigerator", "id", resources.getId());
        refrigerator.copy(resources);
        refrigeratorRepository.save(refrigerator);
        Lock lock = lockRepository.findByCidType(resources.getId(), 3);
        if (lock != null) {
            lock.setMac(resources.getMac());
            lockRepository.save(lock);
        }

    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            Refrigerator refrigerator = refrigeratorRepository.findById(id).orElseGet(Refrigerator::new);
            refrigeratorRepository.deleteById(id);
            Lock lock = lockRepository.findByCidType(refrigerator.getId(), 3);
            if (lock != null) lockRepository.deleteById(lock.getId());
        }
    }

    @Override
    public void download(List<RefrigeratorDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (RefrigeratorDto refrigerator : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("名称", refrigerator.getName());
            map.put("实验室", refrigerator.getLabName());
            map.put("负责人", refrigerator.getAdministratorName());
            if (refrigerator.getTemperature() != null) {
                map.put("温度", refrigerator.getTemperature() + "℃");
            } else {
                map.put("温度", "--℃");
            }
            if (refrigerator.getTemperatureThresholdValue() != null) {
                map.put("温度阈值", refrigerator.getTemperatureThresholdValue() + "℃");
            } else {
                map.put("温度阈值", "--℃");
            }
            if (refrigerator.getHumidity() != null) {
                map.put("湿度", refrigerator.getHumidity() + "%");
            } else {
                map.put("湿度", "--%");
            }
            if (refrigerator.getHumidityThresholdValue() != null) {
                map.put("湿度阈值", refrigerator.getHumidityThresholdValue() + "%");
            } else {
                map.put("湿度阈值", "--%");
            }
            map.put("mac地址", refrigerator.getMac());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void openDoor(Integer id) {
        Refrigerator refrigerator = refrigeratorRepository.findById(id).orElseGet(Refrigerator::new);
        refrigerator.setIsOpen(1);
        refrigeratorRepository.save(refrigerator);
        Lock lock = lockRepository.findByCidType(refrigerator.getId(), 3);
        if (lock == null) {
            lock = new Lock();
            lock.setType(3);
            lock.setCid(refrigerator.getId());
            lock.setMac("");
        }

        lock.setIsOpen(1);
        lockRepository.save(lock);

    }

    @Override
    public void closeDoor(Integer id) {
        Refrigerator refrigerator = refrigeratorRepository.findById(id).orElseGet(Refrigerator::new);
        refrigerator.setIsOpen(0);
        refrigeratorRepository.save(refrigerator);
        Lock lock = lockRepository.findByCidType(refrigerator.getId(), 3);
        lock.setIsOpen(0);
        lockRepository.save(lock);

    }

    @Override
    public List<Refrigerator> list() {
        return refrigeratorRepository.findAllByIsSave();
    }

    @Override
    public List<Refrigerator> listByFloor(Integer floor) {
        return refrigeratorRepository.findAllByFloor(floor);
    }
}
